/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.minidota.model;

import com.minidota.constant.Constant;
import com.minidota.jsonmodels.JsonUnitInfo;
import com.minidota.game.Room;
import com.minidota.impl.HeroesImpl;
import com.minidota.jetty.GameWebSocket;
import com.minidota.utils.Util;
import java.util.ArrayList;

/**
 *
 * @author custom
 */
public class User extends BaseObject {
    //private long id;

    private int id;
    private String snetId;
    private GameWebSocket socket;
    private ArrayList<Vector2> path = new ArrayList<Vector2>();
    private Vector2 nextPoint = new Vector2();
    private boolean disconected = false;
    private int command;//команда которую выполняет обьект
    private int animation; //0 дышит, 1 - бежит, 2 - атака 1
    private long lastAtackTick;// тик в котором была нанесена последняя атака
    //характеристики модели обьекта
    private int heroId;
    private Vector2 speed = new Vector2(); //вектор скорости
    private BaseObject target = null;//цель которую преследует обьект
    private double ticksAddBetweanAttack = 0;//остаток между тиками наращивается для тонкой настройки скорости атаки
    private HeroModel basicHero = null;
    private long tickLastAlive;//тик на котором умер герой
    private double MP; //мана
    private int exp; //Опыт
    private BaseObject selected = this; // выбраный герой тот которого просматривает игрок
    private int tickToRelive = 15;// тиков до оживления
    private int freeWaySign = 0;// по часовой или против обход препядствия определяется перед обходом
    private int visibilityRadius = 500;

    public User() {
        this(null);
    }

    public User(Room room) {
        setRoom(room);
    }

    public Object getJsonData() {
        JsonUnitInfo jui = new JsonUnitInfo();
        jui.setId(getId());
        jui.setGameId(getGameId());
        jui.setSnetId(getSnetId());
        jui.setHeroId(getHeroId());
        jui.setTeamId(getTeamId());
        jui.setTypeId(getBasicHero().getTypeId());
        /*if (this instanceof Creep) {
         jui.setTypeId(4);
         }*/
        return jui;
    }

    @Override
    public void updateData(long tick) {
        super.updateData(tick);
        if (isAlive()) {
            this.tickLastAlive = tick;
            switch (getCommand()) {
                case 0: {
                    setAnimation(0);
                    break;
                }
                case 1: {
                    calcPosition();
                    break;
                }
                case 2: {
                    calcHiting(tick);
                    break;
                }
                default: {
                }
            }
        } else {
            if (tick > this.tickLastAlive + this.tickToRelive) {
                relive();
            }
        }
    }

    public void initPosition() {
        int x = 400;
        int y = 4100;
        if (getTeamId() == 2) {
            x = 4100;
            y = 400;
        }
        Vector2 pos = new Vector2(Util.getRandomInt(x - 200, x + 200), Util.getRandomInt(y - 200, y + 200));
        while (getUserCollision(pos.getX(), pos.getY()) != null) {
            pos = new Vector2(Util.getRandomInt(x - 200, x + 200), Util.getRandomInt(y - 200, y + 200));
        }
        this.setPosition(pos);
    }

    public void resetValues() {
        initPosition();
        this.setSpeed(new Vector2(0, 1));
        this.setViewAngle(0);
        this.setNextPoint(this.getPosition());
        this.setPath(new ArrayList<Vector2>());
        this.setHP(getMaxHP());
        this.setMP(getMaxMP());
        this.setTarget(null);
    }

    public void calcHiting(long tick) {
        if (target != null) {
            setNextPoint(target.getPosition());
            setViewAngle(target.getPosition().sub(getPosition()).calcVector2Angle());
            if (tick - getLastAtackTick() < getTicksForAnimationAttack()) {
                if (getAtackRadius() == getRadius()) {                        //Ближний или дальний бой
                    if (tick == getLastAtackTick() + getTicksForAnimationAttack() - 1) {
                        target.doDamage(this, getDamage()); //Может убить и цель будет сброшена далее надо проверять на нулл
                    }
                } else {
                    if (tick == getLastAtackTick() + Math.round(2 * getTicksForAnimationAttack() / 3)) {
                        new Arrow(this, target).init();
                    }
                }
            }
            if (target != null) {
                if (getPosition().sub(target.getPosition()).lengthSquared() < Math.pow(target.getRadius() + getRadius() + getAtackRadius(), 2)) {
                    if (tick - getLastAtackTick() >= getTicksForAnimationAttack() && tick - getLastAtackTick() >= Math.floor(getTicksBetweanAttack() + getTicksAddBetweanAttack())) {
                        setTicksAddBetweanAttack((getTicksBetweanAttack() + getTicksAddBetweanAttack()) % Math.floor(getTicksBetweanAttack() + getTicksAddBetweanAttack()));
                        setLastAtackTick(tick);
                        setAnimation(2);
                    } else {
                        setAnimation(0);
                    }
                } else {
                    newPath(new Vector2(target.getPosition().getX(), target.getPosition().getY()));
                    calcPosition();
                    setAnimation(1);
                }
            } else {
                setCommand(0);
            }
        } else {
            setCommand(0);
        }
    }

    public int getFreeWaySign(int angle, boolean sign) {
        if (angle < 360) {
            int s = sign ? 1 : -1;
            Vector2 newPosition = getPosition().add(getSpeed().rotate(angle * s));
            BaseObject u = getUserCollision(newPosition.getX(), newPosition.getY());
            boolean isFree = getRoom().getMap().isFreePoint(newPosition.getX(), newPosition.getY());
            if (u == null && isFree) {
                return s;
            } else {
                return getFreeWaySign(angle + (sign ? 0 : 10), !sign);
            }
        } else {
            return 0;
        }
    }

    public Vector2 getFreeWay(int angle, boolean sign) {
        if (angle < 360) {
            int s = sign ? 1 : -1;
            Vector2 newPosition = getPosition().add(getSpeed().rotate(angle * s));
            BaseObject u = getUserCollision(newPosition.getX(), newPosition.getY());
            boolean isFree = getRoom().getMap().isFreePoint(newPosition.getX(), newPosition.getY());
            if (!isFree) {
                if (this.freeWaySign == 1) {
                    this.freeWaySign = -1;
                } else {
                    this.freeWaySign = 1;
                }
                return getFreeWay(angle + 10, !sign);
            }
            if (u == null) {
                setViewAngle(getViewAngle() + angle * s);
                return newPosition;
            } else {
                //return getFreeWay(angle + (sign ? 0 : 10), !sign);
                return getFreeWay(angle + 10, sign);
            }
        } else {
            return null;
        }
    }

    private void delete0PointFromPath() { //Пришел в  0 точку пути 
        if (getPath().size() > 0) {
            getPath().remove(0);
            if (getPath().size() > 1 && getRoom().getMap().isSeeEachOther(getPosition(), getPath().get(1), 20) == null) {
                getPath().remove(0);
            }
            if (getPath().size() > 0) {
                setNextPoint(getPath().get(0));
            } else {
                setNextPoint(getPosition());
            }
        }
    }

    public void calcPosition() {
        Vector2 oldPoint = getPosition();
        if (getPath().size() > 0) {
            if (getPath().get(0).sub(getPosition()).lengthSquared() > 50 * 50) {
                setNextPoint(getPath().get(0));
            } else {
                delete0PointFromPath();
            }
        }
        setSpeed(getNextPoint().sub(getPosition()));
        if (getSpeed().lengthSquared() > getMoveSpeed() * getMoveSpeed()) {
            setSpeed(getSpeed().toLength(getMoveSpeed()));
        }
        if (getSpeed().lengthSquared() > 1) {
            setAnimation(1);
            setViewAngle(getSpeed().calcVector2Angle());
            Vector2 newPosition = getPosition().add(getSpeed());
            if (isFreePoint(newPosition.getX(), newPosition.getY()) || getPath().size() > 0) { //позиция на карте свободна
                BaseObject u = getUserCollision(newPosition.getX(), newPosition.getY());
                if (u == null) {//на новой позиции нет юзера или башни
                    setPosition(newPosition);
                    this.freeWaySign = 0;
                } else {
                    BaseObject uColisNexpPoint = getUserCollision(getNextPoint().getX(), getNextPoint().getY());
                    if (uColisNexpPoint == null || (uColisNexpPoint != null && uColisNexpPoint.getGameId() != u.getGameId())) {
                        if (this.freeWaySign == 0) {
                            this.freeWaySign = getFreeWaySign(0, true);
                        }
                        Vector2 newWayPosition = getFreeWay(10, this.freeWaySign == 1 ? true : false);
                        if (newWayPosition != null) {
                            setPosition(newWayPosition);
                        } else {
                            setNextPoint(getPosition());
                        }
                    } else {
                        Vector2 distansV = u.getPosition().sub(getPosition());
                        setPosition(getPosition().add(distansV.toLength(distansV.length() - getRadius() - u.getRadius())));
                        delete0PointFromPath();
                        this.freeWaySign = 0;
                    }
                }
            } else {
                setNextPoint(getPosition());
            }
        } else {
            setCommand(0);
        }
        /*if (oldPoint.sub(getPosition()).lengthSquared() < 10 * 10) {//если позиуия не изменилась значит куда уперся остановить
         setCommand(0);
         }*/
        //releaseRandomCloission Если случайно где то произошла колизия персонажей.
        /*for (User u : getRoom().getUsers()) {
         if (u.getId() != getId() && u.getPosition().sub(getPosition()).lengthSquared() < Math.pow(u.getRadius() + getRadius(), 2)) {
         Vector2 colisEffect = u.getPosition().sub(getPosition());
         setPosition(getPosition().sub(colisEffect));
         break;
         }
         }*/
    }

    /**
     * @return возвращает данные об объекте клиенту
     */
    @Override
    public String getSendData() {
        StringBuilder sb = new StringBuilder();
        sb.append(Util.getCharByCode(getGameId()));
        sb.append(Util.getCharByCode((int) Math.round(getPosition().getX() * 5)));
        sb.append(Util.getCharByCode((int) Math.round(getPosition().getY() * 5)));
        sb.append(Util.getCharByCode((int) Math.round(getAnimation())));
        sb.append(Util.getCharByCode(getViewAngle()));
        sb.append(Util.getCharByCode(getLvl()));
        sb.append(Util.getCharByCode((int) (getHP() < 0 ? 0 : getHP())));
        sb.append(Util.getCharByCode(getMaxHP()));
        sb.append(Util.getCharByCode((int) (getTicksBetweanAttack() * 10))); //скорость атаки 
        return sb.toString();
    }

    public String getExtendedData() {
        StringBuilder sb = new StringBuilder();
        sb.append(Util.getCharByCode(getGameId()));
        sb.append(Util.getCharByCode(getCurrentStrength()));
        sb.append(Util.getCharByCode(getCurrentAgility()));
        sb.append(Util.getCharByCode(getCurrentIntelligence()));
        sb.append(Util.getCharByCode(getDamage()));
        sb.append(Util.getCharByCode(getArmor()));
        sb.append(Util.getCharByCode((int) (getHP() < 0 ? 0 : getHP())));
        sb.append(Util.getCharByCode(getMaxHP()));
        sb.append(Util.getCharByCode((int) getMP()));
        sb.append(Util.getCharByCode(getMaxMP()));
        sb.append(Util.getCharByCode(getExp()));
        sb.append(Util.getCharByCode(getLvl()));
        return sb.toString();
    }

    public boolean isFreePoint(double nx, double ny) {
        return getRoom().getMap().isFreePoint(nx, ny);
    }

    public BaseObject getUserCollision(double nx, double ny) {
        BaseObject res = null;
        for (User u : getRoom().getUsers()) {
            if (u.getGameId() != getGameId() && u.isAlive() && u.getPosition().sub((new Vector2(nx, ny))).lengthSquared() < Math.pow(u.getRadius() + getRadius(), 2)) {
                res = u;
                break;
            }
        }
        for (Tower t : getRoom().getTowers()) {
            if (t.isAlive() && t.getPosition().sub((new Vector2(nx, ny))).lengthSquared() < Math.pow(t.getRadius() + getRadius(), 2)) {
                res = t;
                break;
            }
        }
        return res;
    }

    public ArrayList<User> getUserCollisionExp() {
        ArrayList<User> users = new ArrayList<User>();
        for (User u : getRoom().getUsers()) {
            if (!(u instanceof Creep) && u.getGameId() != getGameId() && u.isAlive() && u.getTeamId() != getTeamId() && u.getPosition().sub(getPosition()).lengthSquared() < Math.pow(Constant.EXP_RADIUS, 2)) {
                users.add(u);
            }
        }
        return users;
    }

    public User getUserByXY(double nx, double ny) {
        User res = null;
        for (User u : getRoom().getUsers()) {
            if (u.isAlive() && u.getPosition().sub((new Vector2(nx, ny))).lengthSquared() < Math.pow(u.getRadius(), 2)) {
                res = u;
                break;
            }
        }
        return res;
    }

    public BaseObject getObjByGameId(int gameId) {
        BaseObject res = null;
        for (User u : getRoom().getUsers()) {
            if (u.getGameId() == gameId) {
                res = u;
                break;
            }
        }
        for (Tower t : getRoom().getTowers()) {
            if (t.getGameId() == gameId) {
                res = t;
                break;
            }
        }
        return res;
    }

    /**
     * @return the socket
     */
    public GameWebSocket getSocket() {
        return socket;
    }

    /**
     * @param socket the socket to set
     */
    public void setSocket(GameWebSocket socket) {
        this.socket = socket;
    }

    /**
     * @return the id
     */
    public int getId() {
        return id;
    }

    /**
     * @param id the id to set
     */
    public void setId(int id) {
        this.id = id;
    }

    /**
     * @return the speed
     */
    public Vector2 getSpeed() {
        return speed;
    }

    /**
     * @param speed the speed to set
     */
    public void setSpeed(Vector2 speed) {
        this.speed = speed;
    }

    /**
     * @return the nextPoint
     */
    public Vector2 getNextPoint() {
        return nextPoint;
    }

    /**
     * @param nextPoint the nextPoint to set
     */
    public void setNextPoint(Vector2 nextPoint) {
        this.nextPoint = nextPoint;
    }

    /**
     * @param nextPoint the nextPoint to set
     */
    public void newPath(Vector2 nextPoint) {
        //this.nextPoint = nextPoint;
        if (getRoom().getMap().isFreePoint(nextPoint.getX(), nextPoint.getY())) {
            if (getRoom().getMap().isSeeEachOther(getPosition(), nextPoint, 20) == null) {
                this.path = new ArrayList<Vector2>();
                this.nextPoint = nextPoint;
            } else {
                this.path = getRoom().getMap().getPathFromTo(getPosition(), nextPoint);
                if (getPath().size() > 1 && getRoom().getMap().isSeeEachOther(getPosition(), getPath().get(1), 20) == null) {
                    getPath().remove(0);
                }
                this.path.add(nextPoint);
            }
        }
    }

    /**
     * @return the disconected
     */
    public boolean isDisconected() {
        return disconected;
    }

    /**
     * @param disconected the disconected to set
     */
    public void setDisconected(boolean disconected) {
        this.disconected = disconected;
    }

    /**
     * @return the snetId
     */
    public String getSnetId() {
        return snetId;
    }

    /**
     * @param snetId the snetId to set
     */
    public void setSnetId(String snetId) {
        this.snetId = snetId;
    }

    /**
     * @return the heroId
     */
    public int getHeroId() {
        return heroId;
    }

    /**
     * @param heroId the heroId to set
     */
    public void setHeroId(int heroId) {
        this.heroId = heroId;
        this.setBasicHero(HeroesImpl.getHeroByID(heroId));
    }

    /**
     * @return the target
     */
    public BaseObject getTarget() {
        return target;
    }

    /**
     * @param target the target to set
     */
    public void setTarget(BaseObject target) {
        this.target = target;
    }

    /**
     * @return the moveSpeed
     */
    public double getMoveSpeed() {
        return this.getBasicHero().getMoveSpeed();
    }

    /**
     * @return the lastAtackTick
     */
    public long getLastAtackTick() {
        return lastAtackTick;
    }

    /**
     * @param lastAtackTick the lastAtackTick to set
     */
    public void setLastAtackTick(long lastAtackTick) {
        this.lastAtackTick = lastAtackTick;
    }

    /**
     * @return the atackRadius
     */
    public int getAtackRadius() {
        return this.getBasicHero().getAtackRadius();
    }

    /**
     * @return the command
     */
    public int getCommand() {
        return command;
    }

    /**
     * @param command the command to set
     */
    public void setCommand(int command) {
        this.command = command;
        this.freeWaySign = 0;
    }

    /**
     * @return the animation
     */
    public int getAnimation() {
        return animation;
    }

    /**
     * @param animation the animation to set
     */
    public void setAnimation(int animation) {
        this.animation = animation;
    }

    /**
     * @return the CurrentStrength
     */
    public int getCurrentStrength() {
        return (int) (this.getBasicHero().getStrength() + this.getLvl() * this.getBasicHero().getAddStrength()) + (getId() == 9 ? 100 : 0);
    }

    /**
     * @return the CurrentAgility
     */
    public int getCurrentAgility() {
        return (int) (this.getBasicHero().getAgility() + this.getLvl() * this.getBasicHero().getAddAgility() + (getId() == 10 ? 100 : 0));
    }

    /**
     * @return the CurrentAgility
     */
    public int getCurrentIntelligence() {
        return (int) (this.getBasicHero().getIntelligence() + this.getLvl() * this.getBasicHero().getAddIntelligence());
    }

    /**
     * @return the maxHP
     */
    public int getMaxHP() {
        return (int) (this.getBasicHero().getHP()
                + 19 * getCurrentStrength());
    }

    /**
     * @return the maxMP
     */
    public int getMaxMP() {
        return (int) (this.getBasicHero().getMP()
                + 19 * getCurrentIntelligence());
    }

    /**
     * @return the armor
     */
    public int getArmor() {
        return (int) (this.getBasicHero().getArmor()
                + getCurrentAgility() / 7);
    }

    /**
     * @return the damage
     */
    public int getDamage() {
        double tmpDamage = 0;
        if (this.getBasicHero().getTypeId() == 1) {
            tmpDamage = getCurrentStrength();
        } else if (this.getBasicHero().getTypeId() == 2) {
            tmpDamage = getCurrentAgility();
        } else if (this.getBasicHero().getTypeId() == 3) {
            tmpDamage = getCurrentIntelligence();
        }
        return (int) (this.getBasicHero().getDamage() + tmpDamage);
    }

    /**
     * @return the lvl
     */
    public int getLvl() {
        return getLvlByExp(this.getExp());
    }

    /**
     * @return the lvl
     */
    public int getLvlByExp(int exp) {
        int res = 0;
        if (exp < 200) {
            res = 1;
        } else if (exp < 500) {
            res = 2;
        } else if (exp < 900) {
            res = 3;
        } else if (exp < 1400) {
            res = 4;
        } else if (exp < 2000) {
            res = 5;
        } else if (exp < 2600) {
            res = 6;
        } else if (exp < 3200) {
            res = 7;
        } else if (exp < 4400) {
            res = 8;
        } else if (exp < 5400) {
            res = 9;
        } else if (exp < 6000) {
            res = 10;
        } else if (exp < 8200) {
            res = 11;
        } else if (exp < 9000) {
            res = 12;
        } else if (exp < 10400) {
            res = 13;
        } else if (exp < 11900) {
            res = 14;
        } else if (exp < 13500) {
            res = 15;
        } else if (exp < 15200) {
            res = 16;
        } else if (exp < 17000) {
            res = 17;
        } else if (exp < 18900) {
            res = 18;
        } else if (exp < 20900) {
            res = 19;
        } else if (exp < 23000) {
            res = 20;
        } else if (exp < 25200) {
            res = 21;
        } else if (exp < 27500) {
            res = 22;
        } else if (exp < 29900) {
            res = 23;
        } else if (exp < 32400) {
            res = 24;
        } else {
            res = 25;
        }
        return res;

    }

    /**
     * @return the MP
     */
    public double getMP() {
        return MP;
    }

    /**
     * @param MP the MP to set
     */
    public void addMP(double MP) {
        this.setMP(this.getMP() + MP);
    }

    /**
     * оживить игрока
     */
    public void relive() {
        if (getRoom() != null) {
            this.resetValues();
        }
    }

    /**
     * @return the ticksBetweanAttack
     */
    public double getTicksBetweanAttack() {
        double tmpTickBAtack = this.getBasicHero().getTicksBetweanAttack() - this.getBasicHero().getTicksBetweanAttack() * getCurrentAgility() / 100;
        return tmpTickBAtack < 4 ? 4 : tmpTickBAtack;
    }

    /**
     * @return the ticksAddBetweanAttack
     */
    public double getTicksAddBetweanAttack() {
        return ticksAddBetweanAttack;
    }

    /**
     * @param ticksAddBetweanAttack the ticksAddBetweanAttack to set
     */
    public void setTicksAddBetweanAttack(double ticksAddBetweanAttack) {
        this.ticksAddBetweanAttack = ticksAddBetweanAttack;
    }

    public int getTicksForAnimationAttack() {
        return (int) Math.round(getTicksBetweanAttack() / 2);
    }

    /**
     * @return the exp
     */
    public int getExp() {
        return exp;
    }

    /**
     * @param exp the exp to set
     */
    public void addExp(int exp) {
        double percent_hp = 0;
        double percent_mp = 0;
        boolean isLvlUp = false;
        if (getLvl() < getLvlByExp(this.getExp() + exp)) {
            isLvlUp = true;
            percent_hp = getHP() * 100 / getMaxHP();
            percent_mp = getMP() * 100 / getMaxMP();
        }
        this.setExp(this.getExp() + exp);
        if (isLvlUp) {
            this.setHP(percent_hp * getMaxHP() / 100);
            this.setMP(percent_mp * getMaxMP() / 100);
        }
    }

    @Override
    public void doDamage(BaseObject attacker, double damage) {
        addHP(-damage);
        if (!isAlive()) {
            calcKill();
        }
    }

    public void deleteMeFromTargets() {
        for (User u : getRoom().getUsers()) {
            if (u.getTarget() != null && u.getTarget().getGameId() == getGameId()) {
                u.setTarget(null);
            }
        }
        for (Tower t : getRoom().getTowers()) {
            if (t.getTarget() != null && t.getTarget().getGameId() == getGameId()) {
                t.setTarget(null);
            }
        }
    }

    protected void calcKill() {
        deleteMeFromTargets();
        setCommand(0);
        ArrayList<User> users = getUserCollisionExp();
        int exp = 0;
        if (this.getLvl() < 2) {
            exp = 240;
        } else if (this.getLvl() < 3) {
            exp = 280;
        } else if (this.getLvl() < 4) {
            exp = 340;
        } else if (this.getLvl() < 5) {
            exp = 420;
        } else if (this.getLvl() < 6) {
            exp = 520;
        } else if (this.getLvl() < 7) {
            exp = 640;
        } else if (this.getLvl() < 8) {
            exp = 760;
        } else if (this.getLvl() < 9) {
            exp = 880;
        } else if (this.getLvl() < 10) {
            exp = 1000;
        } else if (this.getLvl() < 11) {
            exp = 1120;
        } else if (this.getLvl() < 12) {
            exp = 1240;
        } else if (this.getLvl() < 13) {
            exp = 1360;
        } else if (this.getLvl() < 14) {
            exp = 1480;
        } else if (this.getLvl() < 15) {
            exp = 1600;
        } else if (this.getLvl() < 16) {
            exp = 1720;
        } else if (this.getLvl() < 17) {
            exp = 1840;
        } else if (this.getLvl() < 18) {
            exp = 1960;
        } else if (this.getLvl() < 19) {
            exp = 2080;
        } else if (this.getLvl() < 20) {
            exp = 2200;
        } else if (this.getLvl() < 21) {
            exp = 2320;
        } else if (this.getLvl() < 22) {
            exp = 2440;
        } else if (this.getLvl() < 23) {
            exp = 2560;
        } else if (this.getLvl() < 24) {
            exp = 2680;
        } else if (this.getLvl() < 25) {
            exp = 2800;
        } else if (this.getLvl() < 26) {
            exp = 2920;
        }
        for (User u : users) {
            u.addExp((int) (exp / users.size()));
        }
    }

    /**
     * @return the path
     */
    public ArrayList<Vector2> getPath() {
        return path;
    }

    /**
     * @param path the path to set
     */
    public void setPath(ArrayList<Vector2> path) {
        this.path = path;
    }

    /**
     * @return the selected
     */
    public BaseObject getSelected() {
        return selected;
    }

    /**
     * @param selected the selected to set
     */
    public void setSelected(BaseObject selected) {
        this.selected = selected;
    }

    /**
     * @return the tickToRelive
     */
    public int getTickToRelive() {
        return tickToRelive;
    }

    /**
     * @param tickToRelive the tickToRelive to set
     */
    public void setTickToRelive(int tickToRelive) {
        this.tickToRelive = tickToRelive;
    }

    /**
     * @return the basicHero
     */
    public HeroModel getBasicHero() {
        return basicHero;
    }

    /**
     * @param basicHero the basicHero to set
     */
    public void setBasicHero(HeroModel basicHero) {
        this.basicHero = basicHero;
    }

    /**
     * @param exp the exp to set
     */
    public void setExp(int exp) {
        this.exp = exp;
    }

    /**
     * @param MP the MP to set
     */
    public void setMP(double MP) {
        this.MP = MP;
    }

    /**
     * @return the visibilityRadius
     */
    public int getVisibilityRadius() {
        return visibilityRadius;
    }

    /**
     * @param visibilityRadius the visibilityRadius to set
     */
    public void setVisibilityRadius(int visibilityRadius) {
        this.visibilityRadius = visibilityRadius;
    }
}
